package org.wlld.position;

import org.wlld.entity.NormPosition;
import org.wlld.tools.NormalizationPosition;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @param
 * @DATA
 * @Author LiDaPeng
 * @Description 回归节点
 */
public class PositionOperation extends NormalizationPosition {
    private List<Position> positionList = new ArrayList<>();
    private List<PositionNode> positionNodes = new ArrayList<>();
    private int number;//
    private double sh = 0.01;//样本数量的比例
    private int nodeNumber;

    public void insertXY(Position position) {
        setXY(position.getX(), position.getY());
        positionList.add(position);
    }

    public void setSh(double sh) {
        this.sh = sh / 2;
    }

    public List<Position> start() throws Exception {
        if (positionList.size() >= 9000) {
            int size = positionList.size();
            for (int i = 0; i < size; i++) {
                Position position = positionList.get(i);
                NormPosition normPosition = norm(position.getX(), position.getY());
                position.setX(normPosition.getNormX());
                position.setY(normPosition.getNormY());
                position.norm();
            }
            NormSort normSort = new NormSort();
            Collections.sort(positionList, normSort);
            number = size;
            nodeNumber = (int) Math.sqrt(number);
            //根据范数对所有坐标进行编号，并对坐标进行归一化
            for (int i = 0; i < size; i++) {
                Position position = positionList.get(i);
                position.setId(i);
                position.setSq(i / (double) number);
            }
            for (int i = 0; i < nodeNumber; i++) {
                int startIndex = nodeNumber * i;
                int finishIndex;
                if (i == nodeNumber - 1) {
                    finishIndex = size;
                } else {
                    finishIndex = startIndex + nodeNumber;
                }
                List<Position> positions = positionList.subList(startIndex, finishIndex);
                positionNodes.add(new PositionNode(positions));
            }
            return positionList;
        } else {
            throw new Exception("Too few samples: less than 9000");
        }
    }

    public double getDist(double x, double y) {
        NormPosition normPosition = norm(x, y);
        x = normPosition.getNormX();
        y = normPosition.getNormY();
        int size = positionList.size();
        int key = 0;
        double minDist = -1;
        for (int i = 0; i < size; i++) {
            double xp = positionList.get(i).getX();
            double yp = positionList.get(i).getY();
            double dist = Math.sqrt(Math.pow(x - xp, 2) + Math.pow(y - yp, 2));
            if (minDist < 0 || dist < minDist) {
                minDist = dist;
                key = i;
            }
        }
        return key;
    }

    public int[] getRegion(double x, double y) {
        NormPosition normPosition = norm(x, y);
        double xNorm = normPosition.getNormX();
        double yNorm = normPosition.getNormY();
        double value = 0;
        for (PositionNode positionNode : positionNodes) {
            if (positionNode.isHere(xNorm, yNorm)) {
                value = positionNode.getDist(xNorm, yNorm) * number;
                break;
            }
        }
        if (value < 0) {
            value = 0;
        }
        if (value > number) {
            value = number;
        }
        double region = number * sh;
        int start = (int) (value - region);
        int end = (int) (value + region);
        if (start < 0) {
            start = 0;
        }
        if (end > number) {
            end = number;
        }
        return new int[]{start, end};
    }
}
